package com.slmxz.tms.common.component;

import com.slmxz.tms.common.constant.RedisConstants;
import com.slmxz.tms.system.model.vo.UserInfoVO;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis组件
 */
@Component
public class RedisService {

    private static RedisTemplate<String, Object> staticRedisTemplate;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @PostConstruct
    public void init() {
        RedisService.staticRedisTemplate = this.redisTemplate;
    }

    public static void set(String key, Object value, long time) {
        staticRedisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
    }

    public static void set(String key, Object value) {
        staticRedisTemplate.opsForValue().set(key, value);
    }

    public static Object get(String key) {
        return staticRedisTemplate.opsForValue().get(key);
    }

    public static boolean del(String key) {
        return staticRedisTemplate.delete(key);
    }

    public static Long del(List<String> keys) {
        return staticRedisTemplate.delete(keys);
    }

    public static Long del(Set<String> keys) {
        return staticRedisTemplate.delete(keys);
    }

    public static boolean expire(String key, long time) {
        return staticRedisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    public static Long getExpire(String key) {
        return staticRedisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    public static boolean hasKey(String key) {
        return staticRedisTemplate.hasKey(key);
    }

    public static List<Object> multiGet(String key, Collection<Object> hashKeys){
        return staticRedisTemplate.opsForHash().multiGet(key,hashKeys);
    }


    public static Long incr(String key, long delta) {
        return staticRedisTemplate.opsForValue().increment(key, delta);
    }

    public static Long decr(String key, long delta) {
        return staticRedisTemplate.opsForValue().increment(key, -delta);
    }

    public static Object hGet(String key, String hashKey) {
        return staticRedisTemplate.opsForHash().get(key, hashKey);
    }

    public static boolean hSet(String key, String hashKey, Object value, long time) {
        staticRedisTemplate.opsForHash().put(key, hashKey, value);
        return expire(key, time);
    }

    public static void hSet(String key, String hashKey, Object value) {
        staticRedisTemplate.opsForHash().put(key, hashKey, value);
    }

    public static Map<Object, Object> hGetAll(String key) {
        return staticRedisTemplate.opsForHash().entries(key);
    }

    public static boolean hSetAll(String key, Map<String, Object> map, long time) {
        staticRedisTemplate.opsForHash().putAll(key, map);
        return expire(key, time);
    }

    public static void hSetAll(String key, Map<String, ?> map) {
        staticRedisTemplate.opsForHash().putAll(key, map);
    }

    public static void hDel(String key, Object... hashKey) {
        staticRedisTemplate.opsForHash().delete(key, hashKey);
    }

    public static boolean hHasKey(String key, String hashKey) {
        return staticRedisTemplate.opsForHash().hasKey(key, hashKey);
    }

    public static Long hIncr(String key, String hashKey, Long delta) {
        return staticRedisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    public static Long hDecr(String key, String hashKey, Long delta) {
        return staticRedisTemplate.opsForHash().increment(key, hashKey, -delta);
    }

    public static Set<Object> sMembers(String key) {
        return staticRedisTemplate.opsForSet().members(key);
    }

    public static Long sAdd(String key, Object... values) {
        return staticRedisTemplate.opsForSet().add(key, values);
    }

    public static Long sAdd(String key, long time, Object... values) {
        Long count = staticRedisTemplate.opsForSet().add(key, values);
        expire(key, time);
        return count;
    }

    public static boolean sIsMember(String key, Object value) {
        return staticRedisTemplate.opsForSet().isMember(key, value);
    }

    public static Long sSize(String key) {
        return staticRedisTemplate.opsForSet().size(key);
    }

    public static Long sRemove(String key, Object... values) {
        return staticRedisTemplate.opsForSet().remove(key, values);
    }

    public static List<Object> lRange(String key, long start, long end) {
        return staticRedisTemplate.opsForList().range(key, start, end);
    }

    public static Long lSize(String key) {
        return staticRedisTemplate.opsForList().size(key);
    }

    public static Object lIndex(String key, long index) {
        return staticRedisTemplate.opsForList().index(key, index);
    }

    public static Long lPush(String key, Object value) {
        return staticRedisTemplate.opsForList().rightPush(key, value);
    }

    public static Long lPush(String key, Object value, long time) {
        Long index = staticRedisTemplate.opsForList().rightPush(key, value);
        expire(key, time);
        return index;
    }

    public static Long lPushAll(String key, Object... values) {
        return staticRedisTemplate.opsForList().rightPushAll(key, values);
    }

    public static Long lPushAll(String key, Long time, Object... values) {
        Long count = staticRedisTemplate.opsForList().rightPushAll(key, values);
        expire(key, time);
        return count;
    }

    public static Long lRemove(String key, long count, Object value) {
        return staticRedisTemplate.opsForList().remove(key, count, value);
    }

    /**
     * 获取全局锁,注意由于此方法不加超时时间,故再调用时需要使用自旋锁对该锁进行释放
     * @param key
     * @return
     */
    public static boolean lock(String key,Object value) {
        //setIfAbsent相当于jedis中的setnx，如果能赋值就返回true，如果已经有值了，就返回false
        //即：在判断这个key是不是第一次进入这个方法
        if (staticRedisTemplate.opsForValue().setIfAbsent(key, value)) {
            //第一次，即：这个key还没有被赋值的时候
            return true;
        }
        return false;
    }

    public static boolean lock(String key, Object value, int times) {
        if (staticRedisTemplate.opsForValue().setIfAbsent(key, value, Duration.ofSeconds(times))) {
            //第一次，即：这个key还没有被赋值的时候
            return true;
        }
        return false;
    }

    /**
     * 释放全局锁
     * @param key
     */
    public static void unlock(String key) {
        if (staticRedisTemplate.opsForValue().get(key) != null) {
            staticRedisTemplate.opsForValue().getOperations().delete(key);
        }
    }

    public static Set<String> keys(String pattern) {
        return staticRedisTemplate.opsForValue().getOperations().keys(pattern);
    }

    /**
     *
     * @param account
     * @return 根据用户登录的账号，以及用户类别信息获取缓存中的用户
     */
    public static UserInfoVO getUser(String account){
        return (UserInfoVO)RedisService.get(RedisConstants.LOGIN_USER_PREFIX + ":" + account);
    }

    public static void setUser(UserInfoVO user,long expireTime){
        RedisService.set(RedisConstants.LOGIN_USER_PREFIX + ":" + user.getUsername(),user,expireTime);
    }

    public static void removeUser(String account){
        RedisService.del(RedisConstants.LOGIN_USER_PREFIX + ":" + account);
    }
}
